package com.coszero.utilslibrary.file;

import android.content.res.AssetManager;
import android.os.Build;
import android.os.Environment;
import android.util.Log;

import com.coszero.utilslibrary.utils.LogX;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.file.FileSystemException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;

/**
 * Desc： 文件控制
 * 通常文件控件的操作有 复制 移动 删除 新增
 *
 * @author xmqian
 * Email:xmqian93@163.com
 * Date: 2020/10/12 0012 14:52
 * @version 1
 */
public class FileControl {
    private static final String TAG = "fileControl";
    // <editor-fold desc="文件复制" defaultstate="collapsed">

    /**
     * 复制文件
     *
     * @param source 输入文件
     * @param target 输出文件
     */
    public static void copy(File source, File target) {
        FileInputStream fileInputStream = null;
        FileOutputStream fileOutputStream = null;
        try {
            fileInputStream = new FileInputStream(source);
            fileOutputStream = new FileOutputStream(target);
            byte[] buffer = new byte[1024];
            while (fileInputStream.read(buffer) > 0) {
                fileOutputStream.write(buffer);
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (fileInputStream != null) {
                    fileInputStream.close();
                }
                if (fileOutputStream != null) {
                    fileOutputStream.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }

    /**
     * 复制文件
     *
     * @param filename 文件名
     * @param bytes 数据
     */
    public static void copy(String filename, byte[] bytes) {
        try {
            //如果手机已插入sd卡,且app具有读写sd卡的权限
            if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
                FileOutputStream output = null;
                output = new FileOutputStream(filename);
                output.write(bytes);
                Log.i("FileUtils", "copy: success" + filename);
                output.close();
            } else {
                Log.i("FileUtils", "copy:fail, " + filename);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 从asset文件夹中复制文件
     *
     * @param assets Context.getAssets()
     * @param source assets文件夹中文件的路径或文件名称
     * @param dest 复制文件的目标路径,绝对路径,包含文件名
     * @param isCover 是否覆盖 true覆盖 false如果已有就不进行复制
     * @throws IOException IOException
     * @permission 读写
     */
    public static void copy(AssetManager assets, String source, String dest, boolean isCover)
            throws IOException {
        File file = new File(dest);
        if (isCover || !file.exists()) {
            InputStream is = null;
            FileOutputStream fos = null;
            try {
                is = assets.open(source);
                String path = dest;
                fos = new FileOutputStream(path);
                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = is.read(buffer, 0, 1024)) >= 0) {
                    fos.write(buffer, 0, size);
                }
            } finally {
                if (fos != null) {
                    try {
                        fos.close();
                    } finally {
                        if (is != null) {
                            is.close();
                        }
                    }
                }
            }
        }
    }

    public static void copy(AssetManager assets, String source, String dest)
            throws IOException {
        //默认覆盖
        copy(assets, source, dest, true);
    }
    //</editor-fold>

    // <editor-fold desc="文件删除" defaultstate="collapsed">


    /**
     * 删除目录下的所有文件及文件夹
     *
     * @param root 目录
     */
    public static void deleteAllFiles(File root) {
        File files[] = root.listFiles();
        if (files != null)
            for (File f : files) {
                if (f.isDirectory()) { // 判断是否为文件夹
                    deleteAllFiles(f);
                    try {
                        f.delete();
                    } catch (Exception e) {
                    }
                } else {
                    if (f.exists()) { // 判断是否存在
                        deleteAllFiles(f);
                        try {
                            f.delete();
                        } catch (Exception e) {
                        }
                    }
                }
            }
    }
    //</editor-fold>

    // <editor-fold desc="文件新增" defaultstate="collapsed">

    /**
     * 判断是否有该文件夹,没有则创建文件夹
     *
     * @param dirPath 文件路径
     * @return 是否有该文件路径
     */
    public static boolean makeDir(String dirPath) {
        return FileDirPathUtils.makeDir(dirPath);
    }


    //</editor-fold>

    // <editor-fold desc="文件移动" defaultstate="collapsed">

    /**
     * 移动文件到指定文件夹
     *
     * @param fromFile 需要被移动的目标文件
     * @param toDir 移动的指定文件夹
     * @return 是否移动成功
     */
    public static boolean moveFileToDir(File fromFile, File toDir) {
        if (!toDir.exists()) {
            toDir.mkdirs();
        }
        return move(fromFile, toDir);
    }

    /**
     * 移动文件
     *
     * @param fromFile 需要被移动的目标文件
     * @param toFile 移动到指定文件夹,此为文件对象,不是文件夹,如果是文件夹必须要该文件夹先存在
     * @return 是否移动成功
     */
    public static boolean move(File fromFile, File toFile) {
        //判断被移动的文件是否存在
        if (!fromFile.exists()) {
            throw new NullPointerException("需要移动的目标文件不存在");
        }
        //fromFile是文件,toFile是文件夹,将toFile拼接成文件
        if (toFile.exists() && toFile.isDirectory() && fromFile.isFile()) {
            toFile = new File(toFile.getAbsolutePath() + File.separator + fromFile.getName());
        }
        //创建文件夹
        if (!toFile.getParentFile().exists()) {
            toFile.getParentFile().mkdirs();
        }
        //8.0才可以使用jdk1.8的方法
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            Path fromPath = fromFile.toPath();
            Path toPath = toFile.toPath();
            if (toFile.exists() && toFile.isDirectory()) {
                LogX.i(TAG, "moveData copyDir");
                return moveDirs(fromFile, toFile);
            } else {
                try {
                    LogX.i(TAG, "moveData Files.move");
                    Files.move(fromPath, toPath, StandardCopyOption.ATOMIC_MOVE);
                    return true;
                } catch (FileSystemException e) {
                    //toFile没有对应文件夹会报此错
                    e.printStackTrace();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        } else {
            if (toFile.exists() && toFile.isDirectory()) {
                LogX.i(TAG, "moveData copyDir");
                return moveDirs(fromFile, toFile);
            } else {
                boolean result = fromFile.renameTo(toFile);
                LogX.i(TAG, "moveData renameTo result " + result);
                return result;
            }
        }
        return false;
    }

    /**
     * 移动文件夹
     *
     * @param fromDir 需要被移动的目标文件夹
     * @param toDir 移动到指定文件夹目录
     * @return 是否移动成功
     */
    public static boolean moveDirs(File fromDir, File toDir) {
        boolean moveDirFiles = true;
        if (fromDir == null || toDir == null) {
            return false;
        }

        if (!toDir.exists()) {
            toDir.mkdirs();
        }

        String sourceS = fromDir.getPath();
        String targetS = toDir.getPath();
        String[] paths = fromDir.list();

        for (String tmp : paths) {
            File tmpFile = new File(sourceS + File.separator + tmp);
            File newFile = new File(targetS + File.separator + tmp);
            if (tmpFile.isDirectory()) {
                moveDirFiles = moveDirs(tmpFile, newFile);
            } else {
                moveDirFiles = move(tmpFile, newFile);
            }
        }
        return moveDirFiles;
    }
    //</editor-fold>
}
